#!/bin/sh
# - runtime
# - seed
# - group
# - number

. $LKP_SRC/lib/env.sh
. $LKP_SRC/lib/reproduce-log.sh

## A Linux System call fuzz tester

[ -n "$seed" ] || {
	seed_source="$tbox_group/$rootfs/$kconfig"

	if has_cmd cksum; then
		seed=$(echo "$seed_source" | cksum)
		seed=${seed%% *}
	else
		seed=$(echo "$seed_source" | md5sum | cut -c1-5)
		seed=$(( 0x$seed ))
	fi

	echo "Seeding trinity by $seed based on $seed_source"
}

[ -n "$number" ] || {
	if [ -n "$runtime" ]; then
		number=999999999
	else
		number=99999
	fi
}

# group format: group-05
if [ -n "$group" ]; then
	if [ "${group#*sys_}" != "$group" ]; then
		# stress test for single syscall
		cmd="trinity -q -q -l off -s $seed -N $number -c ${group#*sys_}"
	else
		max_group_nr=5
		targets=
		# trinity -L
		# entrypoint 433 fspick : [64-bit] Enabled
		# entrypoint 434 pidfd_open : [64-bit] Enabled
		# entrypoint 435 clone3 : [64-bit] Enabled AVOID
		for syscall in $(trinity -L | grep "entrypoint .* Enabled" | awk '{print $3}' | sort -u)
		do
			echo "$syscall" | grep -qE "^(get_robust_list|remap_file_pages|ni_syscall)$" && continue
			echo "$syscall" | grep -qE "^[a-z0-9_]*$" || continue
			num=$(echo "$syscall" | md5sum | cut -c1-2)
			num=$(( 0x$num ))
			[ group-0$(( seed % num % max_group_nr )) = "$group" ] && targets="$targets -c $syscall"
		done

		cmd="trinity -q -q -l off -s $seed -N $number $targets"
	fi
else
	cmd="trinity -q -q -l off -s $seed -x get_robust_list -x remap_file_pages -N $number"
fi

# suppress "Killed" message to stderr
set +m

has_cmd trinity || {
	 [ -x /lkp/benchmarks/trinity/bin/trinity ] && ln -sf /lkp/benchmarks/trinity/bin/trinity /bin/trinity
}

has_cmd trinity || {
	echo "trinity is not installed" >&2
	exit 1
}

start_time=$(date +%s)

cd /tmp || exit
if chroot --help 2>&1 | grep -q -- --userspec; then
	if [ $os == "centos" ]; then
		log_cmd chroot --userspec nobody:nobody / $cmd 2>&1 &
	else
		log_cmd chroot --userspec nobody:nogroup / $cmd 2>&1 &
	fi
else
	log_cmd $cmd -X 2>&1 &
fi

pid=$!

if [ -n "$runtime" ]; then
	sleep $runtime
	kill -9 $pid
else
	wait $pid
fi

end_time=$(date +%s)
# end time is wrong in some trinity tests, not root cause yet:
# grep -e start_time -e end_time /result/trinity/group-01-99999/vm-snb/yocto-x86_64-minimal-20190520.cgz/x86_64-rhel-8.3/gcc-9/34bfc452f977849cca0fb57f8b46f4bff67e1969/4/job.yaml
# start_time: '1622552630'
# end_time: '68764814'

# $ date -d @1622552630
# Tue Jun  1 21:03:50 CST 2021

# $ date -d @68764814
# Tue Mar  7 05:20:14 CST 1972
[ "$end_time" -lt "$start_time" ] && log_cmd hwclock --hctosys
